﻿namespace MetaProperties.Framework
{
    using System;
    using System.Collections.Generic;
    using System.Linq.Expressions;

    /// <summary>
    /// Encapsulates the configuration information for a MetaProperty.
    /// </summary>
    public class MetaPropertyConfiguration
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="MetaPropertyConfiguration"/> class.
        /// </summary>
        /// <param name="host">The host of the MetaProperty.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="attributes">The attributes.</param>
        public MetaPropertyConfiguration(object host, string propertyName, params Attribute[] attributes)
            : this(host, propertyName, (IEnumerable<Attribute>)attributes)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="MetaPropertyConfiguration"/> class.
        /// </summary>
        /// <param name="host">The host of the MetaProperty.</param>
        /// <param name="propertyName">Name of the property.</param>
        /// <param name="attributes">The attributes.</param>
        public MetaPropertyConfiguration(object host, string propertyName, IEnumerable<Attribute> attributes)
        {
            this.Host = host;
            this.PropertyName = propertyName;

            if (attributes == null)
            {
                this.Attributes = new List<Attribute>();
            }
            else
            {
                this.Attributes = new List<Attribute>(attributes);
            }
        }

        /// <summary>
        /// Gets the host of the MetaProperty.
        /// </summary>
        /// <value>The host of the MetaProperty.</value>
        public object Host
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the name of the property.
        /// </summary>
        /// <value>The name of the property.</value>
        public string PropertyName
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the attributes associated with the MetaProperty.
        /// </summary>
        /// <value>The attributes.</value>
        public IEnumerable<Attribute> Attributes
        {
            get;
            private set;
        }

        /// <summary>
        /// Creates a MetaProperty configuration instance.
        /// </summary>
        /// <typeparam name="THost">The type of the host.</typeparam>
        /// <typeparam name="TValue">The type of the value.</typeparam>
        /// <param name="host">The host of the MetaProperty.</param>
        /// <param name="propertyExpression">The property expression.</param>
        /// <param name="attributes">The attributes.</param>
        /// <returns>The MetaProperty configuration.</returns>
        public static MetaPropertyConfiguration Create<THost, TValue>(THost host, Expression<Func<THost, TValue>> propertyExpression, params Attribute[] attributes)
        {
            return new MetaPropertyConfiguration(host, PropertyNameHelper.GetProperty(propertyExpression).Name, attributes);
        }

        /// <summary>
        /// Creates a MetaProperty configuration instance.
        /// </summary>
        /// <typeparam name="THost">The type of the host.</typeparam>
        /// <typeparam name="TValue">The type of the value.</typeparam>
        /// <param name="host">The host of the MetaProperty.</param>
        /// <param name="propertyExpression">The property expression.</param>
        /// <param name="attributes">The attributes.</param>
        /// <returns>The MetaProperty configuration.</returns>
        public static MetaPropertyConfiguration Create<THost, TValue>(THost host, Expression<Func<THost, TValue>> propertyExpression, IEnumerable<Attribute> attributes)
        {
            return new MetaPropertyConfiguration(host, PropertyNameHelper.GetProperty(propertyExpression).Name, attributes);
        }
    }
}
